-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ignore validation options and static methods for validation of claims independent to token parsing #175
Conversation
Please write the tests in Groovy - we have standardized on it for testing and it's even easier than Java. We won't accept a PR with Java tests or without 100% coverage. |
Actually, we can convert the Java to Groovy - I don't want to discourage your PR. If you can though, please try! |
Ok, i will give a try. Thanks. And sorry for the test coverage :( |
No worries! We're happy to have the help! |
Do you have an idea how can fix that https://coveralls.io/jobs/18754160/source_files/1580589642#L15 ? Thanks. |
* @return the parser for method chaining. | ||
* @see SignatureException | ||
*/ | ||
JwtParser ignoreSignature(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we want to allow this - it is not good for a spec-compliant parser to allow avoiding mandated security rules. It's probably better to catch the exception and then ignore it if you want to - otherwise it is not obvious in code that you're ignoring security checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok we can remove this method. Security comes first. :)
* | ||
* @since 0.8 | ||
*/ | ||
public class JwtParts { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not entirely correct. A JWT can be a JWS or JWE, and they have different numbers of 'parts' (Unsecured JWT = 2 parts, JWS = 3, JWE = 5). Whatever implementation we'd have around that needs to account for any/all 3 of these scenarios, and probably typed accordingly, e.g. JwsParts extends JwtParts
and JweParts extends JwtParts
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because JWE is being implemented in the jwe
branch, you might not need to worry about jwe parts yet, but whatever implementation we create should be extensible enough to support that upcoming feature/release.
if (!this.ignoreExpiry) { | ||
//https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-30#section-4.1.4 | ||
//token MUST NOT be accepted on or after any specified exp time: | ||
ValidationHelper.validateExpiration(header, claims, this.allowedClockSkewMillis, this.clock); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No static/helper methods in the implementation please. Such methods are not object-oriented - they are more procedural and harder to test.
/** | ||
* This class contains static methods for validation of JWT claims. | ||
*/ | ||
public class ValidationHelper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please no 'Helper' or 'Utils' or such classes for anything other than things that augment the Java language itself (e.g. Strings.whatever, Objects.whatever, Assert.whatever are fine because they augment the Java language and those things are often not overridable - such as String being final) - these typically often represent procedural (non OO) logic.
If anything, this would be a Validator
or something similarly named. Additionally, anything that can be configured/overridable should be an interface and a default implementation provided so that people can plug in different implementations or override them as desired, e.g. Validator
and DefaultValidator
(assuming it is correct to have such a component).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upon further review of this class, it appears the most OO/pluggable way for this it to have a generic Validator
interface and you could have multiple implementations, e.g. ExpirationValidator
PrematureValidator
, etc. For example:
public interface Validator<T> {
public void validate(T value);
}
And the type used by the parser would be Validator<Claims>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok i will made some changes and remove that static methods. Thanks for advice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with Validator interface, that we cannot put additional method parameters into the validate method. For example for checking expires claim we need to optionally provide allowedClockSkewMillis or clock. Do you have any suggestion for this?
I added a code review - the use of the static class is why you're getting code coverage failures. HTH! |
- Remove ValidationHelper and its static methods. - Create JwsParts class and extend it from JwtParts - Implement validation methods inside of JwtParser according to OO principals. - P.S.: Unit tests follows...
Hi @lhazlewood, can you please check my changes again. Thx. :) |
* @param jwt the compact serialized JWT to check | ||
* @return {@code true} if the specified JWT compact string is expired, {@code false} otherwise. | ||
*/ | ||
boolean isExpired(String jwt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this or isPremature
is necessary - just parse the JWT - if there is an exception, you know it isn't a valid JWT. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean isPremature or isExpired or both? In our use case we need really first ignore the expiration validation and then separately check if the token expired or not. I don't really know, if there are other cases for isPremature out there. From my point of view, we can kick all ignoreNotBefore, isPremature and validateNotBefore methods entirely. But why not let them there, may be some one need them for a specific use case.
@@ -0,0 +1,32 @@ | |||
package io.jsonwebtoken; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be in the io.jsonwebtoken.impl
package - we don't want JJWT users to be able to use this class directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I will change this.
* | ||
* @throws ExpiredJwtException if the validation of 'expiration time' ({@code exp}) claim is failed. | ||
*/ | ||
void validateExpiration(String jwt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There could be a lot of validation scenarios - I don't feel we should represent them as individual methods on the parser. Same with validateNotBefore
. What is the desire for these methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isExpired method is just a wrapper on validateExpiration. I explained already above in my first comment, why we need isExpired method. So in my case again we can let validateExpiration method private. But again why to remove this method? Both validateExpiration and validateNotBefore methods was in the code already, just there was a part of the huge parse method. I only moved that parts of the code into the smaller methods and made them accessible. So the decision is up to you.
@@ -0,0 +1,52 @@ | |||
package io.jsonwebtoken; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
io.jsonwebtoken.impl
Any decisions? |
Are there anything else that I can do for a PR acceptance? |
If my PR less likely to be accepted, I would open a new feature request for setting clock skew seperately for notBefore and expiry claims. So that I can at least explicitly set a great amount of clock skew to simulate ignore expiry behaviour. Currently if I set the clock skew value, it affects both nb and exp claim validation. Thanks. |
Hi @selimok - sorry - we just haven't had time to review this due to conferences (Gartner, re:Invent) and holiday/end-of-quarter deadlines. We'll review this as soon as we can! |
Hi @lhazlewood, no problem. Sorry for my impatience. |
@selimok No worries! I'm sorry for the delay! We really appreciate your patience, and we're grateful for the PR! |
Hey, what's the status of this pr? We are also trying to accomplish a validation without expiration date even though it's contained in the jwt. |
Wow @selimok delivers a PR and all the requested changes but 6 months later there is still no feedback from the devs. 6 months! |
Any update for the future of this PR? |
Any update on this? |
Bump, this feature is important for a project I am working on |
Years after the PR, all the quick fix @selimok done. still not merged... now I bet too much conflicts to merge... contribute they said... |
@jonalbertini we're taking a different route with a proper See #474 |
Closing just as a matter of housekeeping in favor of the work that will be done via #474. If you feel otherwise, please let us know and we can discuss. |
This pull request contains the features requested in #80 and additionally code refactoring to reuse claim validation codes in static validation methods.
With these changes we can:
Use case: As part of our token expiration strategy, we create tokens with short life spans and re-create new tokens if needed. To do this in more convenient way, we need aforementioned ignore methods while parsing. This way we can do additional security checks like XSRF token validation or check JWT integrity by validating signature seperately, even if the JWT token expired.
P.S.: I must add new unit test as Java code, since I have no idea how to write code in groovy. Additionally I made some code refactoring and splitted huge methods into smaller. I hope the names of new methods are appropriate to existing (if any) naming conventions.
Thanks.